package de.zainodis.commons.component.ui.widget;

import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.widget.EditText;
import de.zainodis.commons.LogCat;
import de.zainodis.commons.R;
import de.zainodis.commons.model.CurrencyAmount;
import de.zainodis.commons.model.SelectMode;
import de.zainodis.commons.utils.StringUtils;
import de.zainodis.commons.utils.UserInterfaceUtils;

public class CurrencyField extends EditText {

   private static final String TAG = "CurrencyField";
   private CurrencyAmount currency = null;

   public CurrencyField(Context context) {
	 this(context, null);
   }

   public CurrencyField(Context context, AttributeSet attributes) {
	 super(context, attributes);
	 UserInterfaceUtils.setSelectMode(SelectMode.Replace, this);

	 addTextChangedListener(new TextWatcher() {

	    @Override
	    public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
	    }

	    @Override
	    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
	    }

	    @Override
	    public void afterTextChanged(Editable arg0) {
		  CharSequence newText = getText();
		  String newValue = newText != null ? newText.toString() : StringUtils.EMPTY;

		  // Java 1.5 compliance, starting from java 1.6 = isEmpty()
		  if (!newValue.equals(StringUtils.EMPTY)) {
			/*
			 * It may be, that the input value has already been formatted, so
			 * make sure to parse it, if it's not yet formatted.
			 */
			try {
			   currency = create(newValue);
			   // Clear previous error states
			   setError(null);

			} catch (IllegalArgumentException e) {
			   LogCat.w(TAG, "Failed to parse " + newValue, e);
			   // Value is currently invalid, maybe the user isn't done yet
			   setError(String.format(getContext().getString(R.string.invalid_amount), newValue));
			}
		  } else {
			// User deleted value
			currency = create("0");
			setError(null);
		  }
	    }
	 });

   }

   protected void onGainedFocus() {
	 // Does nothing by default
   }

   /**
    * Formats the user input if focus has been lost.
    */
   protected void onLostFocus() {

	 if (currency == null) {
	    // Check if there is a value set on the text field
	    String fieldValue = getText().toString();
	    if (StringUtils.EMPTY.equals(fieldValue)) {
		  // Field is actually empty, nothing else to do here
		  return;
	    }

	    /*
	     * The field value is set, but the currency value is not, hence it is
	     * most likely, that the field value is invalid.
	     */
	    throw new IllegalArgumentException();
	 }
	 try {
	    // Format the input value
	    setText(currency.format());

	 } catch (IllegalArgumentException e) {
	    LogCat.e(TAG, "Failed to parse " + currency);

	    setError(String.format(getContext().getString(R.string.invalid_amount),
			currency.toString()));
	 }

   }

   public boolean isValid() {
	 return getError() != null;
   }

   /**
    * Subclasses may override this method to add locales when creating the
    * currency amount.
    * 
    * @param value
    *           the new value.
    * @return an instance of {@link CurrencyAmount} that holds the given value.
    */
   protected CurrencyAmount create(String value) {
	 return new CurrencyAmount(value);
   }

   public CurrencyAmount getAmount() {
	 return currency;
   }
}
